package top.wilbert.collegelink.user.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import top.wilbert.collegelink.common.exception.BizCodeEnum;
import top.wilbert.collegelink.common.utils.R;
import top.wilbert.collegelink.common.vo.UserResponseVo;
import top.wilbert.collegelink.user.dao.UserDao;
import top.wilbert.collegelink.user.entity.UserEntity;
import top.wilbert.collegelink.user.feign.ThirdPartFeignService;
import top.wilbert.collegelink.user.service.UserService;
import top.wilbert.collegelink.user.vo.UserLoginVo;
import top.wilbert.collegelink.common.utils.PageUtils;
import top.wilbert.collegelink.common.utils.Query;
import top.wilbert.collegelink.user.vo.UserUpdatePasswordVo;
import top.wilbert.collegelink.user.vo.UserUpdatePhoneVo;

import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;


@Service("userService")
public class UserServiceImpl extends ServiceImpl<UserDao, UserEntity> implements UserService {

    @Autowired
    private ThirdPartFeignService thirdPartFeignService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserEntity> page = this.page(
                new Query<UserEntity>().getPage(params),
                new QueryWrapper<UserEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public UserResponseVo login(UserLoginVo userLoginVo) {
        String phone = userLoginVo.getPhone();
        String password = userLoginVo.getPassword();

        //1、去数据库查询
        UserDao userDao = this.baseMapper;
        UserEntity userEntity = userDao.selectOne(new QueryWrapper<UserEntity>().eq("phone", phone));
        if (userEntity == null) {
            //手机号错误
            return null;
        } else {
            //1、获取到数据库的登录密码字段（加密字段）
            String passwordDb = userEntity.getPassword();
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            //2、密码匹配
            boolean matches = passwordEncoder.matches(password, passwordDb);
            if (matches) {
                //密码正确
                UserResponseVo userResponseVo = new UserResponseVo();
                BeanUtils.copyProperties(userEntity, userResponseVo);
                return userResponseVo;
            } else {
                //密码错误
                return null;
            }
        }
    }

    @Override
    public UserResponseVo searchUserByPhone(String phone) {
        UserResponseVo userResponseVo = new UserResponseVo();
        UserEntity userEntity = baseMapper.selectOne(new QueryWrapper<UserEntity>().eq("phone", phone));
        if(userEntity != null){
            BeanUtils.copyProperties(userEntity, userResponseVo);
        }else {
            userResponseVo = null;
        }

        return userResponseVo;
    }

    @Override
    public void setPassword(UserUpdatePasswordVo userUpdatePasswordVo) {

        //密码要进行加密存储，这里使用的是spring家的BCryptPasswordEncoder
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encode = passwordEncoder.encode(userUpdatePasswordVo.getPassword());

        UserEntity userEntity = new UserEntity();
        userEntity.setUserId(userUpdatePasswordVo.getUserId());
        userEntity.setPassword(encode);
        userEntity.setWithPassword(1);
        baseMapper.updateById(userEntity);
    }

    @Override
    public UserResponseVo uploadAvatar(String avatarUrl, Long userId) {
        UserEntity userEntity = new UserEntity();
        userEntity.setAvatarUrl(avatarUrl);
        userEntity.setUserId(userId);
        baseMapper.updateById(userEntity);

        UserEntity entity = baseMapper.selectById(userId);
        UserResponseVo userResponseVo = new UserResponseVo();
        BeanUtils.copyProperties(entity, userResponseVo);
        return userResponseVo;
    }

    @Override
    public UserResponseVo updatePhone(UserUpdatePhoneVo userUpdatePhoneVo) {
        UserEntity userEntity = new UserEntity();
        userEntity.setUserId(userUpdatePhoneVo.getUserId());
        userEntity.setPhone(userUpdatePhoneVo.getPhone());
        baseMapper.updateById(userEntity);

        UserEntity entity = baseMapper.selectById(userEntity.getUserId());
        UserResponseVo userResponseVo = new UserResponseVo();
        BeanUtils.copyProperties(entity, userResponseVo);
        return userResponseVo;
    }

    @Override
    public R smsSendCode(String phone, String authServerConstant) {
        //1、接口防刷
        String redisCode = stringRedisTemplate.opsForValue().get(authServerConstant + phone);
        if (!StringUtils.isEmpty(redisCode)) {
            long l = Long.parseLong(redisCode.split("_")[1]);
            if (System.currentTimeMillis() - l < 60000) {
                //60秒内不能再发
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMessage());
            }
        }

        //2、验证码的再次校验。redis。存key-phone,value-code sms:code:18268718173 -> 12345
        //String code = UUID.randomUUID().toString().substring(0, 5);
        Random random = new Random();
        int i = random.nextInt();
        String code = (i + "").substring(1, 5);
        String saveCode = code + "_" + System.currentTimeMillis();
        //redis缓存验证码，防止同一个phone在60秒内再次发送验证码
        stringRedisTemplate.opsForValue().set(authServerConstant + phone, saveCode, 10, TimeUnit.MINUTES);
        thirdPartFeignService.sendCode(phone, code);

        return R.ok();
    }

}